﻿using System;
using System.Collections.Generic;
using System.Linq;
//using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
//using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
//using System.Windows.Media.Animation;
//using System.Windows.Shapes;
using Microsoft.Phone.Controls;
//using Microsoft.Phone.Info;
//using System.Text;
using Microsoft.Phone.Shell;
using System.Collections;
using System.Collections.ObjectModel;
using Microsoft.Advertising.Mobile.UI;
using Microsoft.Phone.Tasks;
using System.IO;
using System.Windows.Media.Imaging;
using DailyBread.DataServiceReference;
using System.Diagnostics;
//using Microsoft.Phone.Notification;
using System.IO.IsolatedStorage;
using System.Xml.Linq;

namespace DailyBread
{
    public partial class MainPage : PhoneApplicationPage
    {
        public App currentApp { get; set; }
        
        #region comments private variables
        //private int numberofComments = 0;
        private ListBoxItem commentListBoxItem;
        private ObservableCollection<DailyBreadComments> comments = new ObservableCollection<DailyBreadComments>();
        #endregion

        #region Notification service private variables
        //private HttpNotificationChannel httpChannel;
        const string channelName = "DailyBreadUpdatesChannel";
        const string fileName = "PushNotificationsSettings.dat";
        const int pushConnectTimeout = 30;
        #endregion

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Default_Loaded);
            currentApp = ((App)Application.Current);
            if (currentApp.appBarEventsRegistered == false)
            {   // check so that we don't add the event handlers multiple times
                (ApplicationBar.Buttons[0] as ApplicationBarIconButton).Click += new EventHandler(ApplicationBarHome_OnClick);
                (ApplicationBar.Buttons[1] as ApplicationBarIconButton).Click += new EventHandler(ApplicationBarPrevious_OnClick);
                (ApplicationBar.Buttons[2] as ApplicationBarIconButton).Click += new EventHandler(ApplicationBarNext_OnClick);
                (ApplicationBar.Buttons[3] as ApplicationBarIconButton).Click += new EventHandler(ApplicationBarAmen_OnClick);
                currentApp.appBarEventsRegistered = true;
            }


            //if (!TryFindChannel())
            //    DoConnect();
            //AdControl.TestMode = false;
        }

        private void Default_Loaded(object sender, RoutedEventArgs e)
        {
            //PanoramaBG.FetchImage(
            //    delegate(ImageBrush imgBrush)
            //    {
            //        System.Threading.Thread.Sleep(2000);
            //        PanoramaControl.Background = imgBrush;
            //    }); 


            SolidColorBrush backgroundBrush = App.Current.Resources["PhoneBackgroundBrush"] as SolidColorBrush;
            if (currentApp.setting.LightBG == true)
            {   // with light background, don't use the bing image
                PanoramaControl.Background = backgroundBrush;
            }
            else
            {
                if (currentApp.setting.UseSolidBG == true)
                {
                    PanoramaControl.Background = backgroundBrush;
                }
                else
                {
                    PanoramaBG.GetBingImage(
                        delegate(Uri imgUri)
                        {
                            PanoramaControl.Background = new ImageBrush
                            {
                                ImageSource = new BitmapImage(imgUri)
                            };
                            Debug.WriteLine("\nimage src set at " + System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff"));
                        }
                    );
                }
            }
            ResourceDictionary res = App.Current.Resources;
            SolidColorBrush bgBrush = res["TransparentBackground"] as SolidColorBrush;
            bgBrush.Opacity = currentApp.setting.BGShade;

            Reload();         
        }

        public void Reload()
        {
            ShowComments();

            // Get Fav Count and display it if there's any
            Util.GetFavCountFromAzure(currentApp.context.currentDisplayDate,
                delegate(IEnumerable<DailyBreadFavorites> favorites)
                {
                    try
                    {
                        bool state = false;
                        if (favorites != null)
                        {
                            DailyBreadFavorites fav = favorites.First();
                            int count = fav.Count;
                            if (count > 0)
                            {
                                currentApp.context.Favorite = fav;
                                FavCount.Text = count.ToString();
                                state = true;
                            }
                        }
                        ToggleFavCount(state);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                        ToggleFavCount(false);
                    }
                },
                delegate(Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    ToggleFavCount(false);
                });

            // set fav state to false to start with
            ToggleFav(false);

            // check to see if the verse is a personal favorite
            DailyVerse dv = Util.FindAmen(currentApp.context.currentDisplayDate);
            if (dv != null)
            {
                if (dv.personalFav)
                {
                    ToggleFav(true);
                }
                if (dv.verseContent == null)
                {   // this favorite is set before we implemented cache, we need to continue to populate the cache
                    ToggleFav(true);
                    FetchBread(currentApp.context.currentDisplayDate);
                }

                // poplulate UI elements
                Article.Text = dv.breadContent;
                Article.FontSize = currentApp.setting.TextFontSize;
                Verse.Text = dv.verseContent;
                Verse.FontSize = currentApp.setting.TextFontSize;
                RefBible.Text = dv.verseName;
                RefBibleOnCommentsPage.Text = dv.verseName;

                // populate context
                currentApp.context.VerseName = dv.verseName;
                currentApp.context.VerseContent = dv.verseContent;
                currentApp.context.BreadContent = dv.breadContent;
                currentApp.context.BreadName = dv.breadName;
                currentApp.context.ArticleVerse = dv.articleVerse;

            }
            else
            {
                // set loading state to true since we'll start the http request
                ToggleBreadProgressIndicator(true);

                FetchBread(currentApp.context.currentDisplayDate);
            }

            // pre fetch tomorrow's bread
            if (currentApp.context.currentDisplayDate >= System.DateTime.Today)
                PreFetchBread(currentApp.context.currentDisplayDate.AddDays(1));

        }

        // pre fetch future bread and cache it
        private void PreFetchBread(DateTime date)
        {
            // if exists, do nothing
            if (Util.FindAmen(date) != null)
                return;

            AppContext tmpCtx = new AppContext(date);

            Uri uri = Util.GetNavUrl(date);
            if (null != uri)
            {

                // retrieve the daily bread content
                HttpService.Get(uri,
                    delegate(string getResults)
                    {
                        try
                        {
                            // get the reference bible href and verse string
                            int startIndex = getResults.IndexOf("blank") + 7;
                            int endIndex = getResults.IndexOf("</a>", startIndex);
                            tmpCtx.VerseName = getResults.Substring(startIndex, endIndex - startIndex);

                            // retrieve the bible verse
                            startIndex = getResults.IndexOf("http://mobile");
                            endIndex = getResults.IndexOf("\"", startIndex);
                            Uri refUri = new Uri(getResults.Substring(startIndex, endIndex - startIndex));
                            HttpService.Get(refUri,
                                delegate(string refBibleResults)
                                {
                                    try
                                    {

                                        tmpCtx.VerseContent = Util.ExtractVerseContent(refBibleResults);
                                        Util.RecordAmen(tmpCtx, false);
                                    }
                                    catch (Exception ex)
                                    {
                                        Debug.WriteLine(ex.ToString());
                                    }
                                },
                                delegate(string uriString, Exception ex)
                                {
                                    Debug.WriteLine(ex.ToString());
                                });


                            #region save info for favorite
                            // save the title and verse in case users want to save as favorite
                            // Get the Daily bread topic name
                            int breadNameStartPos = getResults.IndexOf("<div class=\"headtop\">") + 21;
                            int breadNameEndPos = getResults.IndexOf("</div><div id=\"article-passage\">");
                            tmpCtx.BreadName = getResults.Substring(breadNameStartPos, breadNameEndPos - breadNameStartPos);

                            // Get the short verse 
                            int articleverseStartingPos = getResults.IndexOf("article-verse\">") + 15;
                            int articleverseEndPos = getResults.IndexOf("<a title", articleverseStartingPos);
                            string verse = getResults.Substring(articleverseStartingPos, articleverseEndPos - articleverseStartingPos);

                            int verseStartPos = getResults.IndexOf("_blank", articleverseEndPos) + 8;
                            int verseEndPos = getResults.IndexOf("</a>", verseStartPos);
                            tmpCtx.ArticleVerse = verse + " " + getResults.Substring(verseStartPos, verseEndPos - verseStartPos);

                            // save the bread content
                            tmpCtx.BreadContent = Util.ExtractBreadContent(getResults);
                            #endregion
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                        }
                    },
                    delegate(string breadUri, Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    });
            }
        }

        // Fetch today's bread
        private void FetchBread(DateTime date)
        {
            Uri uri = Util.GetNavUrl(date);
            if (null != uri)
            {

                // retrieve the daily bread content
                HttpService.Get(uri,
                    delegate(string getResults)
                    {
                        try
                        {
                            // get the reference bible href and verse string
                            int startIndex = getResults.IndexOf("blank") + 7;
                            int endIndex = getResults.IndexOf("</a>", startIndex);
                            RefBible.Text = getResults.Substring(startIndex, endIndex - startIndex);
                            RefBibleOnCommentsPage.Text = RefBible.Text;

                            // retrieve the bible verse
                            startIndex = getResults.IndexOf("http://mobile");
                            endIndex = getResults.IndexOf("\"", startIndex);
                            Uri refUri = new Uri(getResults.Substring(startIndex, endIndex - startIndex) + "&version=NKJV");
                            HttpService.Get(refUri,
                                delegate(string refBibleResults)
                                {
                                    try
                                    {
                                        // set loading state to false since we are ready to render the text
                                        ToggleBreadProgressIndicator(false);

                                        Verse.Text = Util.ExtractVerseContent(refBibleResults);
                                        Verse.FontSize = currentApp.setting.TextFontSize;

                                        // save verse content for favorite
                                        currentApp.context.VerseContent = Verse.Text;

                                        // cache or save as favorite
                                        Util.RecordAmen(currentApp.context, currentApp.context.IsFav);
                                    }
                                    catch (Exception ex)
                                    {
                                        Debug.WriteLine(ex.ToString());
                                        Verse.Text = "Error retrieving bible verse.";
                                    }
                                },
                                delegate(string uriString, Exception ex)
                                {
                                    Debug.WriteLine(ex.ToString());
                                    Verse.Text = "Error retrieving bible verse.";
                                });

                            Article.Text = Util.ExtractBreadContent(getResults);
                            Article.FontSize = currentApp.setting.TextFontSize;


                            #region save info for favorite
                            // save the title and verse in case users want to save as favorite
                            // Get the Daily bread topic name
                            int breadNameStartPos = getResults.IndexOf("<div class=\"headtop\">") + 21;
                            int breadNameEndPos = getResults.IndexOf("</div><div id=\"article-passage\">");
                            currentApp.context.BreadName = getResults.Substring(breadNameStartPos, breadNameEndPos - breadNameStartPos);

                            // Get the short verse 
                            int articleverseStartingPos = getResults.IndexOf("article-verse\">") + 15;
                            int articleverseEndPos = getResults.IndexOf("<a title", articleverseStartingPos);
                            string verse = getResults.Substring(articleverseStartingPos, articleverseEndPos - articleverseStartingPos);
                            verse = Util.StripHTML(verse);

                            //int verseStartingTagPos = getResults.IndexOf("scripture reference verse");
                            //int verseStartingTagPos2 = getResults.IndexOf("scripture reference verse", verseStartingTagPos + 20);
                            int verseStartPos = getResults.IndexOf("_blank", articleverseEndPos) + 8;
                            int verseEndPos = getResults.IndexOf("</a>", verseStartPos);
                            currentApp.context.ArticleVerse = verse + " " + getResults.Substring(verseStartPos, verseEndPos - verseStartPos);

                            // use the long verse 
                            currentApp.context.VerseName = RefBible.Text;

                            // save the bread content
                            currentApp.context.BreadContent = Article.Text;
                            #endregion
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                            Article.Text = "Error retrieving Daily Bread content.";
                        }
                    },
                    delegate(string breadUri, Exception ex)
                    {
                        BreadProgressBar.IsIndeterminate = false;
                        VerseProgressBar.IsIndeterminate = false;
                        Article.Text = "Error retrieving Daily Bread content.";
                        Verse.Text = "Error retrieving bible verse.";
                        Article.Visibility = Visibility.Visible;
                        Verse.Visibility = Visibility.Visible;
                        Debug.WriteLine(ex.ToString());
                    });
            }
        }

        #region application bar actions
        private void ApplicationBarHome_OnClick(object sender, EventArgs e)
        {
            currentApp.context = new AppContext(System.DateTime.Today);
            Util.AddToLog("HomeButton");
            Reload();
        }

        private void ApplicationBarNext_OnClick(object sender, EventArgs e)
        {
            currentApp.context = new AppContext(currentApp.context.currentDisplayDate.AddDays(1));
            Util.AddToLog("NextButton");

            Reload();
        }

        private void ApplicationBarPrevious_OnClick(object sender, EventArgs e)
        {
            currentApp.context = new AppContext(currentApp.context.currentDisplayDate.AddDays(-1));
            Util.AddToLog("PrevButton");

            Reload();
        }

        private void ApplicationBarAmen_OnClick(object sender, EventArgs e)
        {
            if (currentApp.context.IsFav)
                return;
            
            try
            {
                Util.AddToLog("FavButton");

                Util.RecordAmen(currentApp.context, true);
                ToggleFav(true);
                ToggleFavCount(true);
                FavCount.Text = currentApp.context.Favorite.Count.ToString();
            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

        #endregion

        #region comment panorama item
        private void PostButton_Click(object sender, RoutedEventArgs e)
        {
            string comment = CommentBox.Text;

            // if the comment box is empty, do nothing
            if (String.IsNullOrEmpty(comment) || string.Compare("Share your thoughts...", comment, StringComparison.OrdinalIgnoreCase) == 0)
                return;

            Util.AddToLog("PostComment");

            DateTime postedTime = System.DateTime.UtcNow;

            DailyBreadComments cmtSave = new DailyBreadComments();
            cmtSave.Comment = comment;
            cmtSave.PartitionKey = postedTime.ToString("yyyy");
            cmtSave.RowKey = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - postedTime.Ticks, Guid.NewGuid());
            cmtSave.BreadUrl = Util.GetShortNavUrl(currentApp.context.currentDisplayDate);
            ToggleCommentProgressIndicator(true);
            Util.SaveCommentToAzure(currentApp.context.currentDisplayDate, cmtSave,
                delegate(DailyBreadComments savedComment)
                {
                    //CommentBlock.Text = comment;
                    //CommentPostedTime.Text = "Posted on " + postedTime;
                    SetCommentBoxWatermark();
                    ShowComments();
                },
                delegate(Exception ex)
                {
                    CommentProgressBar.IsIndeterminate = false;
                    Debug.WriteLine(ex.InnerException.Message);
                    MessageBlock.Text = "Comment posting failed.  Please try again later.";
                    MessageBlock.Visibility = Visibility.Visible;
                    PostButton.Visibility = Visibility.Visible;
                    SetCommentBoxWatermark();
                });
        }

        private void ShowComments()
        {
            ToggleCommentProgressIndicator(true);

            Util.GetCommentsFromAzure(currentApp.context.currentDisplayDate,
                delegate(IEnumerable<DailyBreadComments> lists)
                {
                    ToggleCommentProgressIndicator(false);
                    comments.Clear();
                    foreach (DailyBreadComments cmt in lists)
                    {
                        comments.Add(cmt);
                    }
                    if (comments != null && comments.Count != 0)
                    {
                        CommentList.ItemsSource = comments;
                        CommentList.Visibility = Visibility.Visible;
                        MessageBlock.Visibility = Visibility.Collapsed;
                        CommentList.ScrollIntoView(CommentList.Items.First());
                        CommentList.UpdateLayout();

                    }
                    else
                    {
                        MessageBlock.Text = "No comments yet. Be the first one to comment.";
                        MessageBlock.Visibility = Visibility.Visible;
                        CommentList.Visibility = Visibility.Collapsed;
                    }                 
                },
                delegate(Exception ex)
                {
                    Debug.WriteLine(ex.InnerException.Message);
                    MessageBlock.Text = "Error retrieving comments.";
                    MessageBlock.Visibility = Visibility.Visible;
                    CommentList.Visibility = Visibility.Collapsed;
                    CommentProgressBar.IsIndeterminate = false;
                });

        }

        private void CommentBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            CommentBox.Text = "";
        }

        private void CommentBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (CommentBox.Text == "Share your thoughts...")
            {
                CommentBox.Text = "";
            }
            CommentBox.Foreground = App.Current.Resources["PhoneTextBoxForegroundBrush"] as Brush;

        }

        private void CommentBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (CommentBox.Text == String.Empty)
            {
                SetCommentBoxWatermark();
            }
        }

        private void SetCommentBoxWatermark()
        {
            CommentBox.Text = "Share your thoughts...";
            SolidColorBrush Brush2 = new SolidColorBrush();
            Brush2.Color = Colors.Gray;
            CommentBox.Foreground = Brush2;
        }

        private void Comment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point tmpPoint = e.GetPosition(null);
            commentListBoxItem = GetListBoxItem(tmpPoint);
        }

        private ListBoxItem GetListBoxItem(Point pt)
        {
            ListBoxItem item = null;
            List<UIElement> oControls = (List<UIElement>)VisualTreeHelper.FindElementsInHostCoordinates(pt, this);
            foreach (UIElement ctrl in oControls)
            {
                if (ctrl is ListBoxItem)
                {
                    item = (ListBoxItem)ctrl;
                    break;
                }

            }
            return item;
        }

        private void CommentContextMenuDelete_Click(object sender, RoutedEventArgs e)
        {
            DailyBreadComments comment = commentListBoxItem.Content as DailyBreadComments;
            Util.AddToLog("DeleteComment");

            CommentProgressBar.IsIndeterminate = true;
            Util.RemoveComment(comment,
                delegate(DailyBreadComments cmt)
                {  
                    // if azure removal is successful, remove it from UI
                    int index = comments.IndexOf(comment);
                    comments.RemoveAt(index);
                    CommentProgressBar.IsIndeterminate = false;
                },
                delegate(Exception ex)
                {
                    Debug.WriteLine(ex.InnerException.Message);
                    MessageBlock.Text = "Error deleting comment.";
                    MessageBlock.Visibility = Visibility.Visible;
                    CommentList.Visibility = Visibility.Collapsed;
                    CommentProgressBar.IsIndeterminate = false;
                });
        }
        #endregion

        #region state management
        private void ToggleFavCount(bool on)
        {
            if (on)
            {
                FavCount.Visibility = Visibility.Visible;
                Thumbup.Visibility = Visibility.Visible;
            }
            else
            {
                FavCount.Visibility = Visibility.Collapsed;
                Thumbup.Visibility = Visibility.Collapsed;
            }
        }

        private void ToggleFav(bool on)
        {
            if (on)
            {
                FavImg.Visibility = Visibility.Visible;
                FavImg2.Visibility = Visibility.Visible;
                FavImg3.Visibility = Visibility.Visible;
                currentApp.context.IsFav = true;
            }
            else
            {
                FavImg.Visibility = Visibility.Collapsed;
                FavImg2.Visibility = Visibility.Collapsed;
                FavImg3.Visibility = Visibility.Collapsed;
                currentApp.context.IsFav = false;
            }
        }

        private void ToggleBreadProgressIndicator(bool on)
        {
            if (on)
            {   // turn the progress indicator on
                BreadProgressBar.IsIndeterminate = true;
                VerseProgressBar.IsIndeterminate = true;
                Article.Visibility = Visibility.Collapsed;
                Verse.Visibility = Visibility.Collapsed;
                RefBible.Visibility = Visibility.Collapsed;
            }
            else
            {
                BreadProgressBar.IsIndeterminate = false;
                VerseProgressBar.IsIndeterminate = false;
                Article.Visibility = Visibility.Visible;
                Verse.Visibility = Visibility.Visible;
                RefBible.Visibility = Visibility.Visible;
            }
        }

        private void ToggleCommentProgressIndicator(bool on)
        {
            if (on)
            {
                CommentProgressBar.IsIndeterminate = true;
                CommentList.Visibility = Visibility.Collapsed;
                PostButton.Visibility = Visibility.Collapsed;
            }
            else
            {
                CommentProgressBar.IsIndeterminate = false;
                CommentList.Visibility = Visibility.Visible;
                PostButton.Visibility = Visibility.Visible;
            }

        }
        #endregion

        #region Tracing and Status Updates
        private void Trace(string message)
        {
            Debug.WriteLine(message);
        }
        #endregion

        private void Comment_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {
            //PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame;
            //Util.AddToLog("CommentThreadPage");
            //ListBoxItem item = GetListBoxItem(e.GetPosition(null));
            //currentApp.context.SelectedComment = item.Content as DailyBreadComments;
            //root.Navigate(new Uri("/Views/CommentThreadPage.xaml", UriKind.Relative));
        }

    }
}
    